﻿@using HardHatCore.HardHatC2Client.Plugin_Management;
@using MudBlazor
@using HardHatCore.HardHatC2Client.Services
@using HardHatCore.HardHatC2Client.Models
@using HardHatCore.HardHatC2Client.Utilities
@using HardHatCore.HardHatC2Client.Pages
@using System.Text

@if (Settings._InteractInputMode == InteractCommandEntryWindow.InteractInputMode.Inline)
{
<MudGrid>
    <MudItem xs="12" sm="12" md="12" lg="12">
        <MudAutocomplete style="background:#111111; color:white;" Strict="true" T="string" ResetValueOnEmptyText="true" SearchFunc="@SearchCommand" ValueChanged="(e) => OnCommandSelected(e)"
                         Dense="true" Margin="Margin.Dense" SelectValueOnTab="true" SelectOnClick="false" CoerceText="false" CoerceValue="true"
                         InputMode="InputMode.text" Variant="Variant.Text" Adornment="Adornment.Start" AdornmentText="[COMMAND]> " Immediate="true" Clearable="true" KeyDownPreventDefault="true" KeyUpPreventDefault="true" TextUpdateSuppression="@TextSuppersion">
        </MudAutocomplete>
    </MudItem>
    @if (SelectedCommandItem != null)
    {
        foreach (var key in SelectedCommandItem.Keys)
        {
            <MudItem xs="12" sm="6" md="4" lg="3">
                <div class="m-2">
                    <label>@key.Name</label>
                    <CommandKeyInput CommandKey="@key" Value="@keyValue[key.Name]" ValueChanged="@(value => UpdateKeyValue(key.Name, value))" />
                </div>
            </MudItem>
        }
    }
    </MudGrid>
}
else if (Settings._InteractInputMode == InteractCommandEntryWindow.InteractInputMode.Modal_Window)
{
    <MudGrid>
        <MudItem xs="12" sm="12" md="12" lg="12">
            <MudAutocomplete MaxItems="@((InteractCommandEntryWindow.AutocompleteSearchShowAllItems) ? (int?)null : 10)" Strict="true" T="string" ResetValueOnEmptyText="true" SearchFunc="@SearchCommand" ValueChanged="(e) => OnCommandSelected(e)"
                             Dense="true" Margin="Margin.Dense" SelectValueOnTab="true" SelectOnClick="false" CoerceText="false" CoerceValue="true"
                             InputMode="InputMode.text" Variant="Variant.Text" Adornment="Adornment.Start" AdornmentText="[COMMAND]> " Immediate="true" Clearable="true" KeyDownPreventDefault="true" KeyUpPreventDefault="true" TextUpdateSuppression="@TextSuppersion">
            </MudAutocomplete>
        </MudItem>
    </MudGrid>
}


@code {

    [Inject]
    private IDialogService? DialogService { get; set; }
    public string? SelectedCommand { get; set; }
    public CommandItem? SelectedCommandItem { get; set; }
    public Dictionary<string, string> keyValue = new();
    public static bool TextSuppersion = true;

    [Parameter] public List<CommandItem>? Commands { get; set; }
    [Parameter] public EventCallback<string> OnContentChanged { get; set; }
    [Parameter] public EventCallback OnEnterKeyDown { get; set; }
    [Parameter]
    public string ImplantName { get; set; } = "";

    public CommandSelection(string implantName)
    {
        ImplantName = implantName;
    }
    public CommandSelection()
    {

    }

    private void UpdateContent()
    {
        var commandString = new StringBuilder(SelectedCommand);
        foreach (var keyValuePair in keyValue)
        {
            commandString.Append($" {keyValuePair.Key} {keyValuePair.Value}");
        }
        OnContentChanged.InvokeAsync(commandString.ToString());
    }


    public async Task<IEnumerable<string>> SearchCommand(string searchText)
    {
        var cmdVal_base = PluginService.GetCommandValidationPlugin(ImplantName);
        
        if (Settings._InteractInputMode == InteractCommandEntryWindow.InteractInputMode.Classic || Settings._InteractInputMode == InteractCommandEntryWindow.InteractInputMode.NoAutoComplete)
        {
            if (InteractCommandEntryWindow.AutocompleteSearchShowAllItems)
            {
                //if input is blank or null give the whole list.
                if (string.IsNullOrEmpty(searchText))
                {
                    var list = cmdVal_base.CommandList.Select(x => x.Usage);
                    //alpabatize the list by the Name before returning it
                    return list.OrderBy(x => x);
                }
                //return the name of the Help.MenuItem that matches the search term
                var resultItem = await Task.FromResult(cmdVal_base.CommandList.Where(x => x.Name.ToLower().Contains(searchText.ToLower())).ToList());
                //alphabetize and return the list
                var nameList = resultItem.Select(x => x.Usage);
                return nameList.OrderBy(x => x);
            }
            else
            {
                if (!string.IsNullOrEmpty(searchText))
                {
                    //return the name of the ImplantCommandValidation_Base CommandList item that starts with the same input
                    var resultItem = await Task.FromResult(cmdVal_base.CommandList.Where(x => x.Name.ToLower().StartsWith(searchText.ToLower())).ToList());
                    //alphabetize and return the list
                    var nameList = resultItem.Select(x => x.Usage);
                    return nameList.OrderBy(x => x);
                }
                else
                {
                    return new List<string>();
                }
            }
        }

        if (InteractCommandEntryWindow.AutocompleteSearchShowAllItems)
        {
            //if input is blank or null give the whole list. 
            if (string.IsNullOrEmpty(searchText))
            {
                var list = cmdVal_base.CommandList.Select(x => x.Name);
                //alpabatize the list by the Name before returning it 
                return list.OrderBy(x => x);
            }
            //return the name of the ImplantCommandValidation_Base that matches the search term
            var resultItem = await Task.FromResult(cmdVal_base.CommandList.Where(x => x.Name.ToLower().Contains(searchText.ToLower())).ToList());
            //alphabetize and return the list
            var nameList = resultItem.Select(x => x.Name);
            return nameList.OrderBy(x => x);
        }
        else
        {
            if (!string.IsNullOrEmpty(searchText))
            {
                //return the name of the ImplantCommandValidation_Base CommandList item that starts with the same input 
                var resultItem = await Task.FromResult(cmdVal_base.CommandList.Where(x => x.Name.ToLower().StartsWith(searchText.ToLower())).Select(x => x.Name));
                return resultItem.OrderBy(x => x);
            }
            else
            {
                return new List<string>();
            }
        }
    }

    private async Task OnCommandSelected(string command)
    {
        var cmdVal_base = PluginService.GetCommandValidationPlugin(ImplantName);
        SelectedCommand = command;
        SelectedCommandItem = cmdVal_base.CommandList.FirstOrDefault(x => x.Name.Equals(command, StringComparison.CurrentCultureIgnoreCase));
        InitializeKeyValue();

        if (SelectedCommandItem != null && Settings._InteractInputMode == InteractCommandEntryWindow.InteractInputMode.Modal_Window)
        {
            var dialogParameters = new DialogParameters
            {
                ["SelectedCommandItem"] = SelectedCommandItem,
                ["keyValue"] = keyValue,
                ["UpdateKeyValue"] = (Func<string, string, Task>)((string keyName, string value) => UpdateKeyValue(keyName, value)),
            };

            var dialogOptions = new DialogOptions { CloseButton = false, DisableBackdropClick = true };
            var dialog = DialogService.Show<CommandInputDialog>("Command Input", dialogParameters, dialogOptions);
            var result = await dialog.Result;

            if (result.Cancelled)
            {
                // recall initKeyValue to reset 
                InitializeKeyValue();
                dialog.Close();
            }
            else
            {
                // Handle the case when the dialog is submitted
                await InteractCommandEntryWindow._onWindowInteractSubmission();
                dialog.Close();
            }
        }
    }

    private void InitializeKeyValue()
    {
        keyValue.Clear();
        if (SelectedCommandItem != null)
        {
            if (SelectedCommandItem.Keys != null)
            {
                foreach (var key in SelectedCommandItem.Keys)
                {
                    keyValue[key.Name] = "";
                }
            }
        }
    }

    private async Task UpdateKeyValue(string keyName, string value)
    {
        keyValue[keyName] = value;
        UpdateContent();
    }
}